//---------------------------------------------------------------------------
// <copyright file="RibbonControlGroup.cs" company="Microsoft Corporation">
//     Copyright (C) Microsoft Corporation.  All rights reserved.
// </copyright>
//---------------------------------------------------------------------------

namespace Microsoft.Windows.Controls.Ribbon
{
    #region Using declarations

    using System;
    using System.Collections.ObjectModel;
    using System.Collections.Specialized;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Markup;
    
    #endregion

    /// <summary>
    ///   Groups a set of Ribbon controls into a visual and conceptual unit.
    /// </summary>
    [ContentProperty("Controls")]
    [TemplatePart(Name = "PART_RibbonControlGroupPanel", Type = typeof(Panel))]
    public class RibbonControlGroup : Control, IRibbonControl
    {
        #region Fields

        /// <summary>
        ///   The template name of the panel that lays out controls in the group.
        /// </summary>
        private const string ControlsPanelTemplateName = "PART_RibbonControlGroupPanel";

        /// <summary>
        ///   The panel that lays out controls within the RibbonControlGroup.
        /// </summary>
        private Panel _controlGroupPanel;        

        /// <summary>
        ///   The set of controls belonging to the gorup.
        /// </summary>
        private ObservableCollection<IRibbonControl> _controls;

        #endregion

        #region Constructors

        /// <summary>
        ///   Initializes static members of the RibbonControlGroup class.
        /// </summary>
        static RibbonControlGroup()
        {
            Type ownerType = typeof(RibbonControlGroup);

            DefaultStyleKeyProperty.OverrideMetadata(ownerType, new FrameworkPropertyMetadata(ownerType));
        }

        #endregion

        #region Public Properties

        /// <summary>
        ///   Gets the set of controls belonging to the RibbonControlGroup.
        /// </summary>
        public Collection<IRibbonControl> Controls
        {
            get
            {
                if (_controls == null)
                {
                    _controls = new ObservableCollection<IRibbonControl>();
                    _controls.CollectionChanged += new NotifyCollectionChangedEventHandler(this.OnControlCollectionChanged);
                }

                return _controls;
            }
        }

        #endregion

        #region Public Methods

        /// <summary>
        ///   Invoked when the control's template is applied.  This adds controls
        ///   belonging to the group to the group's panel for layout.
        /// </summary>
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            // Disconnect the old panel.
            if (_controlGroupPanel != null)
            {
                _controlGroupPanel.Children.Clear();
            }

            _controlGroupPanel = this.GetTemplateChild(ControlsPanelTemplateName) as Panel;

            // Add Controls to the new panel.
            if (_controlGroupPanel != null)
            {
                foreach (IRibbonControl control in this.Controls)
                {
                    FrameworkElement fe = control as FrameworkElement;
                    if (fe != null)
                    {
                        _controlGroupPanel.Children.Add(fe);
                    }
                }
            }
        }

        #endregion

        #region Private Methods

        /// <summary>
        ///   Called when the group's controls collection changes.  When this happens
        ///   we need to update the panel that lays out the controls.
        /// </summary>
        /// <param name="sender">The controls collection that changed.</param>
        /// <param name="e">The event data.</param>
        private void OnControlCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (_controlGroupPanel != null)
            {
                switch (e.Action)
                {
                    case NotifyCollectionChangedAction.Reset:
                        _controlGroupPanel.Children.Clear();
                        foreach (IRibbonControl control in this.Controls)
                        {
                            UIElement uie = control as UIElement;
                            if (uie != null)
                            {
                                _controlGroupPanel.Children.Add(uie);
                            }
                        }

                        break;
                    case NotifyCollectionChangedAction.Add:
                        foreach (UIElement control in e.NewItems)
                        {
                            _controlGroupPanel.Children.Add(control);
                        }

                        break;
                    case NotifyCollectionChangedAction.Remove:
                        foreach (UIElement control in e.OldItems)
                        {
                            _controlGroupPanel.Children.Remove(control);
                        }

                        break;
                    case NotifyCollectionChangedAction.Replace:
                        if (e.NewItems.Count == 1 && e.OldItems.Count == 1)
                        {
                            int index = _controlGroupPanel.Children.IndexOf(e.OldItems[0] as UIElement);
                            if (index >= 0)
                            {
                                UIElement uie = e.NewItems[0] as UIElement;
                                _controlGroupPanel.Children[index] = uie;
                            }
                        }

                        break;
                }
            }
        }

        #endregion
    }
}